package com.ds.lens.data.security;

import com.alibaba.fastjson.JSONObject;
import com.ds.lens.data.common.asserts.Asserts;
import com.ds.lens.data.common.constant.Constants;
import com.ds.lens.data.common.util.HttpUtil;
import com.ds.lens.data.common.util.MD5Util;
import com.ds.lens.data.service.LensAuthService;
import com.ds.lens.data.service.dao.entity.LensUser;
import com.ds.lens.data.vo.out.LoginUserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.message.BasicHeader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.concurrent.TimeUnit;

import static com.ds.lens.data.common.constant.Constants.REDIS_KEY_SESSION;
import static com.ds.lens.data.security.SecuritytConstants.*;

/**
 * @author Gerald Kou
 * @date 2019-04-16
 */
@Slf4j
@Service
public class LoginService {
    @Value("${lens.security.sso.host}")
    private String ssoHost;

    @Value("${lens.security.service.name}")
    private String serviceName;

    /**
     * lens用户session timeout单位为分
     * 默认一天 即1440分钟
     */
    @Value("${lens.security.session.timeout:1440}")
    private long sessionTimeOut;

    @Autowired
    private LensAuthService lensAuthService;

    @Autowired
    private RedisClient redisClient;


    public void lensLogout(HttpServletRequest request) {
//        int loginType = request.getIntHeader(LOGIN_TYPE);
//        if (loginType != Constants.UserTypeEnum.LENS.getCode()) {
//            return;
//        }
        String sessionId = request.getHeader(SecuritytConstants.AUTHORIZATION);
        if (!StringUtils.isEmpty(sessionId)) {
            redisClient.del(REDIS_KEY_SESSION + sessionId);
        }
    }

    public LoginUserVO lensLogin(String userName, String password, HttpServletRequest request) {

        Asserts.assertNotEmpty(userName, Constants.ErrorCode.PARAM_ERROR, "userName can not be empty.");
        Asserts.assertNotEmpty(password, Constants.ErrorCode.PARAM_ERROR, "password can not be empty.");
        LensUser lensUser = lensAuthService.findLensUserByUserName(userName);
        Asserts.assertNotNull(lensUser, Constants.ErrorCode.NO_LENS_USER);
        String pwd = MD5Util.getMD5(password.trim());
        Asserts.assertTrue(pwd.equalsIgnoreCase(lensUser.getPassword()), Constants.ErrorCode.WRONG_PASSWORD);
        HttpSession session = request.getSession();
        String sessionId = session.getId();
        redisClient.setWithExpiration(REDIS_KEY_SESSION + sessionId, userName, sessionTimeOut, TimeUnit.MINUTES);
        return LoginUserVO.builder()
                .sid(sessionId)
                //must not null
                .uid(String.valueOf(lensUser.getId()))
                //must not null
                .username(lensUser.getName())
                //must not null
                .email(lensUser.getEmail())
                .isAdmin(lensAuthService.isAdmin(userName))
                .loginType(Constants.UserTypeEnum.LENS.getCode())
                .build();
    }

    public LoginUserVO ssoLogin(String ticket) {
        String url = SecuritytConstants.PREFIX + ssoHost;
        String getSIDtUrl = url + SecuritytConstants.SID_API + serviceName + TICKET_PARAM + ticket;
        //get session_id from sso by ticket when user login
        ResponseEntity entity = HttpUtil.get(getSIDtUrl, null, null, SSO_TIMEOUT);
        if (null == entity || entity.getStatusCode() != HttpStatus.OK) {
            return null;
        }
        String sessionId = (JSONObject.parseObject(JSONObject.toJSONString(entity.getBody()))).getString(SSO_FILED_SID);
        if (StringUtils.isEmpty(sessionId)) {
            return null;
        }

        //get user info from sso by session_id
        String verifyUrl = url + SecuritytConstants.VERIFY_API;
        Header header = new BasicHeader(SecuritytConstants.AUTHORIZATION, sessionId);
        entity = HttpUtil.get(verifyUrl, null, header, SSO_TIMEOUT);
        log.info("====getUserInfo====" + JSONObject.toJSONString(entity));
        if (null == entity || entity.getStatusCode() != HttpStatus.OK) {
            return null;
        }
        JSONObject repObject = (JSONObject) entity.getBody();

        if (null == repObject.getString(SSO_FILED_UID) ||
                null == repObject.getString(SSO_FILED_USERNAME) ||
                null == repObject.getString(SSO_FILED_EMAIL)) {
            return null;
        }
        return LoginUserVO.builder()
                .sid(sessionId)
                //must not null
                .uid(repObject.getString(SSO_FILED_UID))
                //must not null
                .username(repObject.getString(SSO_FILED_USERNAME))
                .first_name(repObject.getString(SSO_FILED_FIRST_NAME))
                .last_name(repObject.getString(SSO_FILED_LAST_NAME))
                //must not null
                .email(repObject.getString(SSO_FILED_EMAIL))
                .telephone(repObject.getString(SSO_FILED_TELEPHONE))
                .isAdmin(lensAuthService.isAdmin(repObject.getString(SSO_FILED_USERNAME)))
                .loginType(Constants.UserTypeEnum.SSO.getCode())
                .build();
    }
}
